package com.english.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.english.common.AvgTreeMap;
import com.english.common.RankResponse;
import com.english.domain.Record;
import com.english.domain.Student;
import com.english.domain.Text;
import com.english.mappers.RecordMapper;
import com.english.mappers.StudentMapper;
import com.english.mappers.TextMapper;
import com.english.service.RankService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.*;

@Service
public class RankServiceImp implements RankService {
    // 获取当前年份
    private int currentYear;
    // 获取当前月份
    private int currentMonth;
    private int currentTerm;
    RankServiceImp(){
        // 获取当前日期
        LocalDate currentDate = LocalDate.now();
        this.currentMonth = currentDate.getMonthValue();
        this.currentYear = currentDate.getYear();
        if (currentMonth < 8 && currentMonth > 2)
            currentTerm = 1;
        else
            currentTerm = 2;
    }
    @Resource
    StudentMapper studentMapper;
    @Resource
    RecordMapper recordMapper;
    @Resource
    TextMapper textMapper;
    public List<Record> getCurrentTermRecord(){
        QueryWrapper<Record> rqw = new QueryWrapper<>();
        rqw.eq("year", currentYear);
        if(currentMonth > 8 || currentMonth < 3){
            //第一学期
            rqw.le("week", 16);
        }
        else {
            rqw.gt("week", 16);
        }
        return recordMapper.selectList(rqw);
    }
    //根据id返回文章对象
    public Text getTextById(int id){
        QueryWrapper qw = new QueryWrapper();
        qw.eq("id", id);
        return textMapper.selectOne(qw);
    }
    public List<RankResponse> getResultByTreeMap(TreeMap map){
        List<RankResponse> rankResponseList = new ArrayList<>();
        List<Map.Entry<String, Integer>> entryList = new ArrayList<>(map.entrySet());
        // 使用 Comparator 按照 value 值进行排序
        Comparator<Map.Entry<String, Integer>> comparator = Map.Entry.comparingByValue();
        Collections.sort(entryList, comparator.reversed());
        //遍历红黑树, 输出前 10 个键值对
        int count = 0;
        for (Map.Entry<String, Integer> entry : entryList) {
            if (count >= 10) {
                break;
            }
            String key = entry.getKey();
            int value = entry.getValue();
            rankResponseList.add( new RankResponse(key, value, null) );
            count++;
        }
        return rankResponseList;
    }

    public List<RankResponse> getResultByTreeMapDouble(TreeMap map){
        List<RankResponse> rankResponseList = new ArrayList<>();
        List<Map.Entry<String, Double>> entryList = new ArrayList<>(map.entrySet());
        // 使用 Comparator 按照 value 值进行排序
        Comparator<Map.Entry<String, Double>> comparator = Map.Entry.comparingByValue();
        Collections.sort(entryList, comparator.reversed());
        //遍历红黑树, 输出前 10 个键值对
        int count = 0;
        for (Map.Entry<String, Double> entry : entryList) {
            if (count >= 10) {
                break;
            }
            String key = entry.getKey();
            Double value = entry.getValue();
            rankResponseList.add( new RankResponse(key, null, value) );
            count++;
        }
        return rankResponseList;
    }

    private Double getAvgScore(List<Record> recordList) {
        Double sum = Double.valueOf(0);
        for(Record record : recordList ){
            sum += record.getScore();
        }
        Double result = sum / recordList.size();
        return Math.round(result * 100.0) / 100.0;
    }

    public int getCntOfMajorAndWeek(String major, int week){
        return recordMapper.getByMajorAndWeek(major, week).size();
    }
    public Double getScoreOfMajorAndWeek(String major, int week){
        return this.getAvgScore(recordMapper.getByMajorAndWeek(major, week));
    }

    public Double getAvgScoreByDept(String dept){
        return this.getAvgScore(recordMapper.getByDept(dept));
    }

    /*---------👇Implements👇------------*/
    @Override
    public List<RankResponse> getTextByCnt(){
        List<Record> recordList = getCurrentTermRecord();
        TreeMap<String, Integer> map = new TreeMap<>();
        for(int i = 0; i < recordList.size(); i++){
            Record record = recordList.get(i);
            int value = 0;
            if( map.get(String.valueOf(record.getId())) != null){
                value = map.get(String.valueOf(record.getId()));
            }
            map.put(String.valueOf(record.getId()), value + 1);
        }
        return getResultByTreeMap(map);
    }
    @Override
    public List<RankResponse> getDeptByCnt(){
        List<Record> recordList = getCurrentTermRecord();
        TreeMap<String, Integer> map = new TreeMap<>();
        for(int i = 0; i < recordList.size(); i++){
            QueryWrapper qw = new QueryWrapper();
            qw.eq("name", recordList.get(i).getName());
            Student student = studentMapper.selectOne(qw);
            String dept = student.getDept();
            int value = 0;
            if( map.get(dept) != null){
                value = (int)map.get(dept);
            };
            map.put(dept, value + 1);
        }
        return getResultByTreeMap(map);
    }

    @Override
    public List<RankResponse> getMajorByCnt() {
        List<Record> recordList = getCurrentTermRecord();
        TreeMap<String, Integer> map = new TreeMap<>();
        for(int i = 0; i < recordList.size(); i++){
            QueryWrapper qw = new QueryWrapper();
            qw.eq("name", recordList.get(i).getName());
            Student student = studentMapper.selectOne(qw);
            String major = student.getMajor();
            int value = 0;
            if( map.get(major) != null){
                value = (int)map.get(major);
            };
            map.put(major, value + 1);
        }
        return getResultByTreeMap(map);
    }

    @Override
    public List<RankResponse> getClassByCnt() {
        List<Record> recordList = getCurrentTermRecord();
        TreeMap<String, Integer> map = new TreeMap<>();
        for(int i = 0; i < recordList.size(); i++){
            QueryWrapper qw = new QueryWrapper();
            qw.eq("name", recordList.get(i).getName());
            Student student = studentMapper.selectOne(qw);
            String clas = student.getClas();
            int value = 0;
            if( map.get(clas) != null){
                value = (int)map.get(clas);
            }
            map.put(clas, value + 1);
        }
        return getResultByTreeMap(map);
    }

    @Override
    public List<RankResponse> getGradeByCnt() {
        List<Record> recordList = getCurrentTermRecord();
        TreeMap<String, Integer> map = new TreeMap<>();
        for(int i = 0; i < recordList.size(); i++){
            QueryWrapper qw = new QueryWrapper();
            qw.eq("name", recordList.get(i).getName());
            Student student = studentMapper.selectOne(qw);
            String grade = String.valueOf(student.getGrade());
            int value = 0;
            if( map.get(grade) != null){
                value = (int)map.get(grade);
            }
            map.put(grade, value + 1);
        }
        return getResultByTreeMap(map);
    }

    @Override
    public List<RankResponse> getTextByScore() {
        List<Record> recordList = this.getCurrentTermRecord();
        AvgTreeMap avgTreeMap = new AvgTreeMap();
        for (int i = 0; i < recordList.size();i++){
            String id = recordList.get(i).getId();
            Double score = recordList.get(i).getScore();
            avgTreeMap.update( String.valueOf(id), score  );
        }
        return getResultByTreeMapDouble(avgTreeMap.getTreeMap());
    }

    @Override
    public List<RankResponse> getDeptByScore() {
        List<Record> recordList = this.getCurrentTermRecord();
        AvgTreeMap avgTreeMap = new AvgTreeMap();
        for (int i = 0; i < recordList.size();i++){
            QueryWrapper qw = new QueryWrapper();
            qw.eq("name", recordList.get(i).getName());
            Student student = studentMapper.selectOne(qw);
            Double score = recordList.get(i).getScore();
            avgTreeMap.update( String.valueOf( student.getDept() ), score  );
        }
        return getResultByTreeMapDouble(avgTreeMap.getTreeMap());
    }

    @Override
    public List<RankResponse> getMajorByScore() {
        List<Record> recordList = this.getCurrentTermRecord();
        AvgTreeMap avgTreeMap = new AvgTreeMap();
        for (int i = 0; i < recordList.size();i++){
            QueryWrapper qw = new QueryWrapper();
            qw.eq("name", recordList.get(i).getName());
            Student student = studentMapper.selectOne(qw);
            Double score = recordList.get(i).getScore();
            avgTreeMap.update( String.valueOf( student.getMajor() ), score  );
        }
        return getResultByTreeMapDouble(avgTreeMap.getTreeMap());
    }

    @Override
    public List<RankResponse> getClassByScore() {
        List<Record> recordList = this.getCurrentTermRecord();
        AvgTreeMap avgTreeMap = new AvgTreeMap();
        for (int i = 0; i < recordList.size();i++){
            QueryWrapper qw = new QueryWrapper();
            qw.eq("name", recordList.get(i).getName());
            Student student = studentMapper.selectOne(qw);
            Double score = recordList.get(i).getScore();
            avgTreeMap.update( String.valueOf( student.getClas() ), score  );
        }
        return getResultByTreeMapDouble(avgTreeMap.getTreeMap());
    }

    @Override
    public List<RankResponse> getGradeByScore() {
        List<Record> recordList = this.getCurrentTermRecord();
        AvgTreeMap avgTreeMap = new AvgTreeMap();
        for (int i = 0; i < recordList.size();i++){
            QueryWrapper qw = new QueryWrapper();
            qw.eq("name", recordList.get(i).getName());
            Student student = studentMapper.selectOne(qw);
            Double score = recordList.get(i).getScore();
            avgTreeMap.update( String.valueOf( student.getGrade() ), score  );
        }
        return getResultByTreeMapDouble(avgTreeMap.getTreeMap());
    }

    @Override
    public int getCntOfWeek(String username, int week) {
        QueryWrapper qw = new QueryWrapper<>();
        qw.eq("week", week);
        return recordMapper.selectList(qw).size();
    }

    @Override
    public int getCntOfMonth(String username, int month) {
        month *= 4;
        QueryWrapper qw = new QueryWrapper<>();
        qw.gt("week", month - 4);
        qw.le("week", month);
        return recordMapper.selectList(qw).size();
    }

    @Override
    public int getCntOfTerm(String username, int term) {
        if( term == 1 ){
            return getCntOfMonth(username, 3)+getCntOfMonth(username, 4)
                    +getCntOfMonth(username, 5)+getCntOfMonth(username, 6);
        }
        return getCntOfMonth(username, 9)+getCntOfMonth(username, 10)
                        +getCntOfMonth(username, 11)+getCntOfMonth(username, 12);
    }

    @Override
    public int getCntOfYear(String username, int year) {
        QueryWrapper qw = new QueryWrapper<>();
        qw.eq("name", username);
        qw.eq("year", year);
        return recordMapper.selectList(qw).size();
    }

    @Override
    public int getCntOfDept(String dept) {
        return recordMapper.getByDept(dept).size();
    }

    @Override
    public int getCntOfMajor(String major) {
        return recordMapper.getByMajor(major).size();
    }

    @Override
    public int getCntOfClas(String major, int clas) {
        return recordMapper.getByClas(major, clas).size();
    }

    @Override
    public int getCntOfGrade(int grade) {
        return recordMapper.getByGrade(grade).size();
    }

    @Override
    public Double getScoreOfWeek(String username, int week) {
        QueryWrapper qw = new QueryWrapper<>();
        qw.eq("name", username);
        qw.eq("week", week);
        return this.getAvgScore( recordMapper.selectList(qw) );
    }

    @Override
    public Double getScoreOfMonth(String username, int month) {
        month *= 4;
        QueryWrapper qw = new QueryWrapper<>();
        qw.gt("week", month - 4);
        qw.le("week", month);
        return this.getAvgScore( recordMapper.selectList(qw) );
    }

    @Override
    public Double getScoreOfTerm(String username, int term) {
        if( term == 1 ){
            return getScoreOfMonth(username, 3)+getScoreOfMonth(username, 4)
                    +getScoreOfMonth(username, 5)+getScoreOfMonth(username, 6);
        }
        return getScoreOfMonth(username, 9)+getScoreOfMonth(username, 10)
                +getScoreOfMonth(username, 11)+getScoreOfMonth(username, 12);
    }

    @Override
    public Double getScoreOfYear(String username, int year) {
        QueryWrapper qw = new QueryWrapper<>();
        qw.eq("name", username);
        qw.eq("year", year);
        return this.getAvgScore( recordMapper.selectList(qw) );
    }

    @Override
    public Double getScoreOfDept(String dept) {
        return this.getAvgScore(recordMapper.getByDept(dept));
    }

    @Override
    public Double getScoreOfMajor(String major) {
        return this.getAvgScore(recordMapper.getByMajor(major));
    }
    @Override
    public Double getScoreOfClas(String dept, int clas) {
        return this.getAvgScore(recordMapper.getByClas(dept, clas));
    }

    @Override
    public Double getScoreOfGrade(int grade) {
        return this.getAvgScore(recordMapper.getByGrade(grade));
    }

    @Override
    public List<RankResponse> getCntOfMajorByWeek(String major) {
        List<RankResponse> rankResponseList = new ArrayList<>();
        int num = 0;
        //如果是第一学期，从第9周开始计算
        if( this.currentTerm == 1)
            num += 9;
        else {
            num += 33;
        }
        for (int i = 0; i < 16; i++){
            rankResponseList.add(new RankResponse(String.valueOf(i + 1), getCntOfMajorAndWeek(major, num + i), null ));
        }
        return rankResponseList;
    }

    public List<RankResponse> getScoreOfMajorByWeek(String major) {
        List<RankResponse> rankResponseList = new ArrayList<>();
        int num = 0;
        //如果是第一学期，从第9周开始计算
        if( this.currentTerm == 1)
            num += 9;
        else {
            num += 33;
        }
        for (int i = 0; i < 16; i++){
            rankResponseList.add(new RankResponse(String.valueOf(i + 1), null, getScoreOfMajorAndWeek(major, num + i) ));
        }
        return rankResponseList;
    }

    @Override
    public List<RankResponse> getCntOfYearByDept(int year) {
        List<RankResponse> rankResponseList = new ArrayList<>();
        QueryWrapper<Student> qw = new QueryWrapper();
        qw.select("DISTINCT dept");
        List<Student> studentsList = studentMapper.selectList(qw);
        for (int i = 0; i < studentsList.size(); i ++){
            String dept = studentsList.get(i).getDept();
            rankResponseList.add( new RankResponse(dept, getCntOfDept(dept), null ) );
        }
        return rankResponseList;
    }

    @Override
    public List<RankResponse> getScoreOfYearByDept(int year) {
        List<RankResponse> rankResponseList = new ArrayList<>();
        QueryWrapper<Student> qw = new QueryWrapper();
        qw.select("DISTINCT dept");
        List<Student> studentsList = studentMapper.selectList(qw);
        for (int i = 0; i < studentsList.size(); i ++){
            String dept = studentsList.get(i).getDept();
            rankResponseList.add( new RankResponse(dept, null, getAvgScoreByDept(dept) ) );
        }
        return rankResponseList;
    }
}
